package Utils.io.json;

import Utils.io.IOUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.io.InputStream;

/**
 * Json工具类
 *
 * @author d11yu
 */
public final class JacksonUtils {

    private static JacksonUtils instance;
    private static ObjectMapper mapper;

    public ObjectMapper getMapper() {
        return mapper;
    }

    public void setMapper(ObjectMapper mapper) {
        JacksonUtils.mapper = mapper;
    }


    private JacksonUtils(DeserializationFeature feature, boolean state) {
        mapper = new ObjectMapper();
        mapper.configure(feature, state);
    }

    public static JacksonUtils getInstance() {
        return getInstance(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
    }

    public static JacksonUtils getInstance(DeserializationFeature feature, boolean state) {
        if (instance == null) {
            instance = new JacksonUtils(feature, state);
        }
        return instance;
    }

    /**
     * Jackson Json反序列化为List。
     *
     * @param jsonStr
     * @param typeReference 例：new TypeReference<List<Person>>() {}
     * @param <T>
     * @return
     * @throws JsonProcessingException
     */
    public <T> T deserializeListOrMap(String jsonStr, TypeReference<T> typeReference) throws JsonProcessingException {
        return mapper.readValue(jsonStr, typeReference);
    }

    /**
     * Jackson Json反序列化为List。
     *
     * @param is
     * @param typeReference 例：new TypeReference<List<Person>>() {}
     * @param <T>
     * @return
     * @throws JsonProcessingException
     */
    public <T> T deserializeListOrMap(InputStream is, TypeReference<T> typeReference) throws IOException {
        return mapper.readValue(is, typeReference);
    }

    /**
     * Jackson Json反序列化为List。
     *
     * @param path
     * @param typeReference 例：new TypeReference<List<Person>>() {}
     * @param <T>
     * @return
     * @throws JsonProcessingException
     */
    public <T> T deserializeListOrMapFromFile(String path, TypeReference<T> typeReference) throws IOException {
        return mapper.readValue(IOUtils.file2InputStream(path), typeReference);
    }


    /**
     * Jackson Json反序列化为Java Bean
     *
     * @param jsonStr   json字符串
     * @param classType 目标对象类型
     * @return 返回目标对象
     * @throws IOException 异常
     */
    public <T> T deserialize(String jsonStr, Class<T> classType) throws IOException {
        return deserialize(jsonStr, classType, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * Jackson Json反序列化为Java Bean
     *
     * @param jsonStr   json字符串
     * @param classType 目标对象类型
     * @param feature   DeserializationFeature
     * @param state     JavaBean State
     * @return 返回目标对象
     * @throws IOException 异常
     */
    public <T> T deserialize(String jsonStr, Class<T> classType, DeserializationFeature feature, boolean state) throws IOException {
        mapper.configure(feature, state);
        return mapper.readValue(jsonStr, classType);
    }

    /**
     * Jackson Json反序列化为Java Bean
     *
     * @param is        InputStream
     * @param classType 目标对象类型
     * @return 返回目标对象
     * @throws IOException 异常
     */
    public <T> T deserialize(InputStream is, Class<T> classType) throws IOException {
        return deserialize(is, classType, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * Jackson Json反序列化为Java Bean
     *
     * @param is        InputStream
     * @param classType 目标对象类型
     * @param <T>       目标对象类型
     * @param feature   DeserializationFeature
     * @param state     JavaBean State
     * @return 返回目标对象
     * @throws IOException 异常
     */
    public <T> T deserialize(InputStream is, Class<T> classType, DeserializationFeature feature, boolean state) throws IOException {
        mapper.configure(feature, state);
        return mapper.readValue(is, classType);
    }

    /**
     * Jackson Json反序列化为Java Bean
     *
     * @param path      json文件路径
     * @param classType 目标对象类型
     * @return 返回目标对象
     * @throws IOException 异常
     */
    public <T> T deserializeFile(String path, Class<T> classType) throws IOException {
        return deserializeFile(path, classType, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * Jackson Json反序列化为Java Bean
     *
     * @param path      json文件路径
     * @param classType 目标对象类型
     * @param <T>       目标对象类型
     * @param feature   DeserializationFeature
     * @param state     JavaBean State
     * @return 返回目标对象
     * @throws IOException 异常
     */
    public <T> T deserializeFile(String path, Class<T> classType, DeserializationFeature feature, boolean state) throws IOException {
        mapper.configure(feature, state);
        return mapper.readValue(IOUtils.file2InputStream(path), classType);
    }

    /**
     * 序列化对象
     *
     * @param obj
     * @return
     * @throws JsonProcessingException
     */
    public String serialize(Object obj) throws JsonProcessingException {
        return mapper.writeValueAsString(obj);
    }

    /**
     * 序列化对象到JSON文件
     *
     * @param obj
     * @param path
     * @throws IOException
     */
    public void serializeToFile(Object obj, String path) throws IOException {
        String s = serialize(obj);
        IOUtils.String2File(s, path);
    }
}
